home *** CD-ROM | disk | FTP | other *** search
- (*
-
- The * Co-Pascal * COMPILER
-
- ...is a modified version of the PASCAL-S compiler to permit
- interleaved concurrent program execution. The reserved words
- "COBEGIN" and "COEND" mark concurrent blocks while calls to
- the predefined functions WAIT and SIGNAL provide synchronization.
- The changes are from "Principles of Concurrent Programming by
- BEN-ARI.
-
- The defining document for PASCAL-S is:
-
- PASCAL-S: A SUBSET AND ITS IMPLEMENTATION by N. WIRTH.
-
-
- HISTORY:
-
- . PASCAL-S developed by N. Wirth, 1976.
-
- . PASCAL-S modified for the HP/3000 by D. Greer.
-
- . M. Ben-Ari develops additions to the Pascal language to provide
- for simulated concurrency. See Ben-Ari : 'Principles of Concurrent
- Programming. Pretice-Hall, 1982.
-
- . B. Burd incorporates Ben-Ari's changes into PASCAL-S,
- developing CO-PASCAL for the VAX/11-750 under VMS, 1985.
-
- . C. Schoening modifies and enhances CO-PASCAL for Turbo-Pascal v2.0
- under CP/M and MS-DOS, 1985.
-
-
- *)
-
-
- program Co_Pascal( INPUT, OUTPUT );
-
- {$R+}
- {$I HEADER.MOD }
-
- (*------------------------------------------------------COMPILE-----*)
-
- overlay procedure compile;
-
- const KEY : array[1..NKW] of string[10] =
- ( 'AND ', 'ARRAY ',
- 'BEGIN ', 'CASE ',
- 'COBEGIN ', 'COEND ',
- 'CONST ', 'DIV ',
- 'DO ', 'DOWNTO ',
- 'ELSE ', 'END ',
- 'FOR ', 'FUNCTION ',
- 'IF ', 'MOD ',
- 'NOT ', 'OF ',
- 'OR ', 'PROCEDURE ',
- 'PROGRAM ', 'RECORD ',
- 'REPEAT ', 'THEN ',
- 'TO ', 'TYPE ',
- 'UNTIL ', 'VAR ',
- 'WHILE ' );
-
-
- type SYMBOL = ( INTCON, REALCON, CHARCON, WORD,
- PLUS, MINUS, TIMES, IDIV, RDIV, IMOD,
- NOTSY, ANDSY, ORSY,
- EQL, NEQ, GTR, GEQ, LSS, LEQ,
- LPARENT, RPARENT, LBRACK, RBRACK,
- COMMA, SEMICOLON, PERIOD, COLON,
- BECOMES, CONSTSY, TYPESY, VARSY, ARRAYSY, RECORDSY,
- FUNCSY, PROCSY, PROGRAMSY, IDENT, BEGINSY, ENDSY,
- REPEATSY, UNTILSY, WHILESY, DOSY, FORSY,
- IFSY, THENSY, ELSESY, CASESY, OFSY, TOSY, DOWNTOSY );
-
- SYMSET = SET OF SYMBOL;
-
- const KSY : array[1..NKW] of SYMBOL =
- ( ANDSY, ARRAYSY, BEGINSY, CASESY,
- BEGINSY, ENDSY, CONSTSY, IDIV,
- DOSY, DOWNTOSY, ELSESY, ENDSY,
- FORSY, FUNCSY, IFSY, IMOD,
- NOTSY, OFSY, ORSY, PROCSY,
- PROGRAMSY, RECORDSY, REPEATSY, THENSY,
- TOSY, TYPESY, UNTILSY, VARSY,
- WHILESY );
-
- var DISPLAY : ARRAY [ 0 .. LMAX ] of INTEGER;
- SPS : ARRAY [ ' '.. ']' ] of SYMBOL;
-
- (*
- =============================
- key words and special symbols
- =============================
- *)
-
- (* indicies to tables *)
-
- T, (* ---> TAB, *)
- A, (* ---> ATAB, *)
- SX, (* ---> STAB, *)
- C1, (* ---> RCONST, *)
- C2, (* ---> RCONST *)
-
- LC (* program Location Counter *) : INTEGER;
-
- (*
- =========================
- Error Control Variables
- =========================
- *)
-
- ERRS : SET OF 0..ERMAX; (* compilation errors *)
- ERRPOS : INTEGER;
- SKIPFLAG : BOOLEAN; (* used by procedure ENDSKIP *)
-
- (*
- =============================
- Insymbol (scanner) Variables
- =============================
- *)
-
- SY : SYMBOL; (* last symbol read by INSYMBOL *)
- ID : ALFA; (* identifier from INSYMBOL *)
- INUM : INTEGER; (* integer from INSYMBOL *)
- RNUM : REAL; (* real number from INSYMBOL *)
- SLENG : INTEGER; (* string length *)
- CHARTP: ARRAY[CHAR] OF CHTP; (* character types *)
- LINE : ARRAY [1..LLNG] OF CHAR; (* input line *)
- CC : INTEGER; (* character counter *)
- LL : INTEGER; (* length of current line *)
- LINECOUNT: INTEGER; (* source line counter *)
-
-
- (*
- ======
- sets
- ======
- *)
-
- CONSTBEGSYS, TYPEBEGSYS,
- BLOCKBEGSYS, FACBEGSYS, STATBEGSYS : SYMSET;
-
-
-
- (*--------------------------------------------------------ERROR-----*)
-
- procedure ERROR( N : INTEGER );
- (*
- write error on current line & add to TOT ERR
- *)
- begin
- if ERRPOS = 0 then write('[**> ', ' ':6);
- if CC > ERRPOS then begin
- write( ' ': CC-ERRPOS, '^', N:2 );
- ERRPOS := CC+3;
- ERRS := ERRS + [N];
- end;
- end; { ERROR }
-
- (*-----------------------------------------------------ENDSKIP------
-
- ENDSKIP changed to just print blanks for skipped symbols.
- This should cause less confusion than the underlining did.
- *)
-
- procedure ENDSKIP; (* underline skipped part of input *)
- begin
- while ERRPOS < CC do begin
- write(' ');
- ERRPOS := ERRPOS + 1;
- end;
- SKIPFLAG := FALSE;
- end; { ENDSKIP }
-
- procedure FATAL( N : integer ); forward;
- procedure NEXTCH; forward;
-
- (*---------------------------------------------------------EMIT-----
- emit actual code into the code table
- *)
- procedure EMIT(FCT: INTEGER);
- begin
- if LC = CMAX then FATAL(6);
- CODE[LC].F := FCT;
- LC := LC+1;
- end; { EMIT }
-
- procedure EMIT1(FCT,B: INTEGER);
- begin
- if LC = CMAX then FATAL(6);
- with CODE[LC] do begin
- F := FCT;
- Y := B;
- end;
- LC := LC+1;
- end; { EMIT1 }
-
- procedure EMIT2(FCT,A,B: INTEGER);
- begin
- if LC = CMAX then FATAL(6);
- with CODE[LC] do begin
- F := FCT;
- X := A;
- Y := B;
- end;
- LC := LC+1;
- end; { EMIT2 }
-
- (*-----------------------INITTABLES----ERRORMSG----ENTERSTDFCNS-----*)
-
- {$I INIT.MOD }
-
- (*-----------------------------------------------------INSYMBOL-----*)
-
- {$I INSYMBOL.MOD }
-
- (*--------------------------------------------------PRINTTABLES-----
- this procedure prints out the internal compiler and
- interpreter tables. This procedure is called if the
- DEBUG flag is TRUE.
- *)
-
- procedure PRINTTABLES;
- var I: INTEGER;
- O: ORDER;
- begin
- writeln;
- writeln(' Identifiers Link Obj Typ Ref NRM Lev Adr');
- for I := BTAB[1].LAST +1 to T do with TAB[I] do
- writeln(I,' ',NAME,LINK:5, ORD(OBJ):5, ORD(TYP):5, REF:5,
- ORD(NORMAL):5, LEV:5, ADR:5);
- writeln(' Blocks Last LPar PSze Vsze');
- for I := 1 to B do with BTAB[I] do
- writeln(I, LAST:5, LASTPAR:5, PSIZE:5, VSIZE:5);
- writeln;
- writeln(' Arrays Xtyp Etyp Eref Low High Elsz Size');
- for I := 1 to A do with ATAB[I] do
- writeln(I, ORD(INXTYP):5, ORD(ELTYP):5,
- ELREF:5, LOW:5, HIGH:5, ELSIZE:5, SIZE:5);
- writeln(' CODE:');
- for I := 0 to LC-1 do begin
- if I MOD 5 = 0 then begin
- writeln; write(I:5)
- end;
- O := CODE[I];
- write(O.F:5);
- if O.F < 31 then
- if O.F < 4 then write(O.X:2, O.Y:5)
- else write(O.Y:7)
- else write(' ');
- write(',');
- end;
- writeln;
- end; { PRINTTABLES }
-
- (*--------------------------------------------------------BLOCK-----*)
-
- {$I BLOCKA.MOD }
- {$I BLOCKB.MOD }
- {$I BLOCKC.MOD }
-
- (*--------------------------------------------------------FATAL-----*)
-
- procedure FATAL; (* internal table overflow *)
- begin
- if ERRS <> [] then ERRORMSG;
- writeln;
- write( 'COMPILER TABLE for ' );
- case N of
- 1 : write( 'IDENTIFIER' );
- 2 : write( 'PROCEDURES' );
- 3 : write( 'REALS' );
- 4 : write( 'ARRAYS' );
- 5 : write( 'LEVELS' );
- 6 : write( 'CODE' );
- 7 : write( 'STRINGS' );
- end;
- writeln( ' is too SMALL' );
- writeln;
- writeln(' Please take this output to the maintainer of ');
- writeln(' this language for your installation ' );
- writeln; writeln;
- writeln(' FATAL termination of Co-Pascal');
- HALT;
- end; { FATAL }
-
- (*-------------------------------------------------------NEXTCH-----*)
-
- procedure NEXTCH; (* read next char; process line end *)
- begin
- if CC = LL then begin
- if EOF( SOURCE ) then begin
- writeln;
- writeln(' PROGRAM INCOMPLETE');
- ERRORMSG;
- HALT;
- end;
- if ERRPOS <> 0 then begin
- if SKIPFLAG then endSKIP;
- ERRPOS := 0;
- writeln;
- end;
- LINECOUNT := LINECOUNT + 1;
- write( LINECOUNT:4,' ' );
- write( LC:5, ' ' );
- LL := 0;
- CC := 0;
- while NOT EOLN(SOURCE) do begin
- LL := LL+1;
- read( SOURCE,CH);
- write(CH);
- LINE[LL] := CH
- end;
- LL := LL + 1;
- writeln;
- readln( SOURCE );
- LINE[LL] := ' ';
- end;
- CC := CC+1;
- CH := LINE[CC];
- if (ORD(CH) < ORD(' ')) then ERROR(60)
- end; { NEXTCH }
-
-
- begin { COMPILE }
-
- (*
- =============================
- check for program heading
- =============================
- *)
-
- INITIALIZE;
- INSYMBOL;
- if SY <> PROGRAMSY then ERROR(3) else begin
- INSYMBOL;
- if SY <> IDENT then ERROR(2) else begin
- PROGNAME := ID;
- INSYMBOL;
- if SY <> LPARENT then ERROR(9) else repeat
- INSYMBOL;
- if SY <> IDENT then ERROR(2) else begin
- if ID = 'INPUT ' then IFLAG := TRUE
- else if ID = 'OUTPUT ' then OFLAG := TRUE
- else if ( NOT DFLAG ) then begin
- DFILE := ' ';
- M := 0;
- while ID[m+1] in [ 'A'..'Z', '0'..'9', ':' ]
- do M := M + 1;
- MOVE( ID, DFILE[11-m], m );
- DFLAG := TRUE;
- writeln( ' DFLAG <- TRUE ', DFILE, m:5 );
- end else ERROR(0);
- INSYMBOL;
- end;
- until SY <> COMMA;
- if SY = RPARENT then INSYMBOL else ERROR(4);
- if NOT OFLAG then ERROR(20)
- end
- end;
-
- ENTERSTDFCNS;
-
- with BTAB[1] do begin
- LAST := T;
- LASTPAR := 1;
- PSIZE := 0;
- VSIZE := 0
- end;
-
- (*
- ============
- COMPILE
- ============
- *)
-
- block( BLOCKBEGSYS+STATBEGSYS, FALSE, 1 );
-
- if (SY <> PERIOD) then ERROR(22);
- EMIT(31); (* halt *)
- if ( BTAB[2].VSIZE > STMAX-STKINCR * PMAX ) then ERROR(49);
- if DEBUG then PRINTTABLES;
- if ERRS <> [] then begin
- ERRORMSG;
- HALT;
- end;
- end; { COMPILE }
-
- (*----------------------------------------------------INTERPRET------*)
-
- overlay procedure INTERPRET;
-
- {$I INTERPT.MOD }
-
- end; { INTERPRET }
-
- (*---------------------------------------------------P_CODE I/O-----*)
-
- procedure PutBlock( FileName : FNAME );
- var ObjFile : file;
- t : string[ 3];
- len : integer;
-
- begin
- assign( ObjFile, FileName + '.OBJ' );
- rewrite( ObjFile );
- for len := 1 to 25 do SS[len] := ' ';
- len := length( SFILE );
- MOVE( SFILE[1], SS[11-len], len );
- if DFLAG then MOVE( DFILE[1], SS[11], 10 );
- MOVE( IFLAG, SS[21], 1 );
- MOVE( OFLAG, SS[22], 1 );
- MOVE( DFLAG, SS[23], 1 );
- MOVE( B , SS[24], 2 );
-
- blockwrite( ObjFile, TAB, ( SizeOf( TAB) DIV 128 )+1 );
- blockwrite( ObjFile, ATAB, ( SizeOf( ATAB) DIV 128 )+1 );
- blockwrite( ObjFile, BTAB, ( SizeOf( BTAB) DIV 128 )+1 );
- blockwrite( ObjFile, STAB, ( SizeOf( STAB) DIV 128 )+1 );
- blockwrite( ObjFile, CODE, ( SizeOf( CODE) DIV 128 )+1 );
- blockwrite( ObjFile, RCONST, ( SizeOf(RCONST) DIV 128 )+1 );
- blockwrite( ObjFile, SS, ( SizeOf( SS) DIV 128 )+1 );
- close( ObjFile );
- end;
-
- procedure GetBlock( FileName : FNAME );
-
- type temptr = ^tempdat;
- tempdat = array [1..128] of 0..255;
-
- var ObjFile : file;
- a : temptr;
- temp : tempdat;
- len : integer;
-
- procedure B_read( var varname; q : integer );
- begin
- blockread( ObjFile, varname, ( Q DIV 128 ) );
- blockread( ObjFile, temp, 1 );
- a := ptr( Seg(varname), Ofs(varname) + 128*( Q DIV 128 ) );
- move( temp, a^, ( Q MOD 128 ) );
- end;
-
- begin
- assign( ObjFile, FileName + '.OBJ' );
- reset( ObjFile );
- B_read( TAB, SizeOf( TAB ));
- B_read( ATAB, SizeOf( ATAB ));
- B_read( BTAB, SizeOf( BTAB ));
- B_read( STAB, SizeOf( STAB ));
- B_read( CODE, SizeOf( CODE ));
- B_read( RCONST, SizeOf( RCONST ));
- B_read( SS, SizeOf( SS ));
- len := 1;
- while SFILE[len] = ' ' do len := len+1;
- MOVE( SS[len], SFILE[1],10 ); SFILE[0] := CHR( 11-len );
- MOVE( SS[ 21], IFLAG, 1 );
- MOVE( SS[ 22], OFLAG, 1 );
- MOVE( SS[ 23], DFLAG, 1 );
- MOVE( SS[ 24], B, 2 );
- if DFLAG then MOVE( SS[11], DFILE[1], 10 ); DFILE[0] := CHR(10);
- if DEBUG then begin
- writeln;
- write(' S: ',SFILE+'.PAS ');
- if DFLAG then writeln('D: ',DFILE+'.DAT' ) else writeln;
- writeln(' flags I/O/D :',IFLAG:8,OFLAG:6,DFLAG:6,' B : ',B );
- writeln;
- end;
- end;
-
- procedure HELP;
- begin
- writeln;
- writeln(' Selection error. Correct syntax is : FNAME -X* ');
- writeln;
- writeln(' where FNAME is a legal file name with the .TYP optional ');
- writeln(' and the <X> option is one of the following : ');
- writeln;
- writeln(' C :: compile the source code to P-code ');
- writeln(' E :: execute a previously compiled P-code ');
- writeln(' R :: compile and then execute ');
- writeln;
- writeln(' * is an optional flag to display debug information ');
- writeln;
- halt;
- end;
-
- begin { MAIN }
-
- if ( ParamCount < 1 ) then HELP;
- SFILE := ParamStr(1);
- for m := 1 to length( SFILE ) do SFILE[m] := UpCase( SFILE[m] );
- assign( SOURCE, SFILE+'.PAS' );
- {$I-}
- reset( SOURCE )
- {$I+};
- if IOresult <> 0 then begin
- writeln('Cannot find file : ', SFILE+'.PAS' );
- halt;
- end;
- writeln; writeln(' ':10,HEADER); writeln;
-
- if ( ParamCount < 2 ) then begin
- OPTION := 'R';
- DEBUG := FALSE;
- end else begin
- CmdLine := ParamStr(2);
- if ( CmdLine[1] = '-' ) then OPTION := UpCase( CmdLine[2] ) else HELP;
- if ( CmdLine[3] = '*' ) then DEBUG := TRUE else DEBUG := FALSE;
- end;
-
- case OPTION of
-
- 'C' : begin
- COMPILE;
- PutBlock( SFILE );
- end;
-
- 'E' : begin
- GetBlock( SFILE );
- INTERPRET;
- end;
-
- 'R' : begin
- COMPILE;
- writeln;
- writeln(' begin execution for : ', PROGNAME );
- writeln;
- INTERPRET;
- end;
-
- else HELP;
- end;
-
- writeln;
- end.